<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="Cache-Control" content="no-cache">
<meta name="Referrer" content="never">
<title>chessroom</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/index.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.13/theme-chalk/index.min.css" rel="stylesheet">
<style>
div.locX{
	width: 60px;
	display: inline-block;
	font-size: 12px;
	color: black;
}
div.locXStart{
	width: 56px;
}
div.red{
	color: red;
}
div.right, div.left, div.farright, div.app{
	display: inline-block;
}
div.app{
	width: 880px;
	vertical-align: top;
}
div.right{
	width: 450px;
	vertical-align: top;
}
div.farright{
	width: 410px;
	vertical-align: top;
}
div.right > *{
	display: inline-block;
	width: 200px;
	min-width: 200px;
	margin: 0 10px;
}
div.rival{
	font-size: 40px;
	font-weight: bold;
	text-align: center;
	margin: 20px 10px;
}
div.rival-name{
	text-align: center;
	vertical-align: top;
}
div.rival-name-name{
	width: 188px;
	font-size: 20px;
	display: inline-block;
	vertical-align: top;
	line-height: 20px;
	padding: 10px 5px;
	margin: 5px 0;
	border: 2px solid blue;
	border-radius: 40px;
	color: blue;
	word-wrap: break-word;
}
div.rival-name img{
	width: 80px;
	height: 80px;
	margin: 0;
	display: inline-block;
	border-radius: 40px;
}
div.log{
	font-size: 20px;
	text-align: center;
	margin: 5px 10px;
}
.logTest{
	color: red;
}
.logTestSuccess{
	color: blue;
}
div.queue-title{
	font-size: 30px;
	font-weight: bold;
	text-align: left;
	margin: 15px 10px;
	color: blue;
}
div.queue, div.super-chat{
	font-size: 16px;
	text-align: left;
	margin: 5px 10px;
}
div.queue span{
	display: inline-block;
	border-radius: 8px;
	border: 1px solid red;
	color: red;
	margin: -5px 10px;
	padding: 0px 5px;
}
div.queue span.vip{
	color: #f0f;
	border-color: #f0f;
}
div.super-chat-title{
	font-size: 30px;
	font-weight: bold;
	text-align: left;
	margin: 15px 10px;
	color: green;
}
div.timer{
	margin: 20px 20px;
	font-size: 20px;
	vertical-align: top;
	height: 40px;
	line-height: 40px;
}
div.timer > span{
	margin: 0px 0px 0px 20px;
}
#timer-time{
	font-size: 40px;
}
div.peace{
	display: block;
	position: relative;
	top: 57px;
	left: 120px;	
	height: 0;	
}
div.peace > div{
	width: 40px;
	height: 40px;
	font-size: 25px;
	font-weight: bold;
	line-height: 40px;
	color: red;
	border: 3px solid red;
	border-radius: 40px;
}
div.vip{
	display: block;
	position: relative;
	top: -15px;
	left: 72px;	
	height: 0;	
}
div.vip > div{
	width: 50px;
	height: 25px;
	font-size: 22px;
	font-weight: bold;
	line-height: 25px;
	color: #f0f;
	border: 3px solid #f0f;
	border-radius: 40px;
}
div.clock-line{
	font-size: 16px;
	height: 25px;
	margin: 0px 10px;
}
div.clock-line span{
	margin: 0px 20px 0px 0px
}
div#exitGame{
	position: absolute;
	left: 1100px;
	top: 80px;
	font-size: 60px;
	line-height: 80px;
	padding: 10px 20px;
	color: red;
	border: 5px solid red;
	border-radius: 20px;
}
.el-message__content{
	font-size: 20px;
}
.el-notification__content{
    font-size: 20px;
    line-height: 25px;
    color: black;
}
body{
	margin: 8px;
	background-color: #eee;
	height: unset;
}
div#app{
	height: unset;
}
</style>
</head>
<body>
<div class="left">
	<div class="locX locXStart"></div><div class="locX">1</div><div class="locX">2</div><div class="locX">3</div><div 
			class="locX">4</div><div class="locX">5</div><div class="locX">6</div><div class="locX">7</div><div 
			class="locX">8</div><div class="locX">9</div><br>
	<canvas id="canvas" width="600" height="660"></canvas><br>
	<div class="locX locXStart"></div><div class="locX red">九</div><div class="locX red">八</div><div 
			class="locX red">七</div><div class="locX red">六</div><div class="locX red">五</div><div 
			class="locX red">四</div><div class="locX red">三</div><div class="locX red">二</div><div 
			class="locX red">一</div><br>
</div><!-- end of left -->
<div class="app" id="app">
<div class="right">
<div class="rival red">红方</div><div class="rival">黑方</div><br>
<div class="rival-name"><div class="vip" v-if="isVip(red_rival_name)"><div>VIP
		</div></div><div class="peace" v-if="red_peace"><div>{{toPeaceWords(red_peace)}}
		</div></div><img :src="red_image"><div class="rival-name-name">{{red_rival_name}}
		</div></div><div class="rival-name"><div class="vip" v-if="isVip(black_rival_name)"><div>VIP
		</div></div><div class="peace" v-if="black_peace"><div>{{toPeaceWords(black_peace)}}
		</div></div><img :src="black_image"><div class="rival-name-name">{{black_rival_name}}</div></div><br>
<template v-for="log in logs">
<div class="log" v-if='!log.test'>({{log.step}}){{log.content}}</div>
<div class="log logTest" v-if='log.test=="test"'>({{log.step}}){{log.content}}</div>
<div class="log logTestSuccess" v-if='log.test=="success"'>({{log.step}}){{log.content}}</div>
</template>
</div><!-- end of right -->
<div class="farright">
<div class="timer"><img src="clock.svg" width="40px"><span id="timer-text"></span><span id="timer-time"></span><span id="timer-ex"></span></div>
<div class="clock-line"><span id="clock"></span> V2.0.1 Build230915</div>
<div class="queue-title">排队队列</div>
<div class="queue" v-if="queue.length==0">~~队列为空，欢迎排队~~</div>
<template v-for="player in queue">
<div class="queue">{{player.point}}点：<span class="vip" v-if="isVip(player.name)">VIP</span>{{player.name}}<span v-if="player.ready">已准备</span></div>
</template>
<div class="queue">↑↑请输入【排队】参与游戏↑↑</div>
<div class="super-chat-title">留言板(Super Chat)</div>
<div class="super-chat" v-if="messages.length==0">--留言板为空--</div>
<template v-for="message in messages">
<div class="super-chat">{{message.name}}：{{message.text}}</div>
</template>
</div><!-- end of farright -->
<div id="exitGame" v-if="exit">即将下播<br>停止排队</div>
</div><!-- end of app -->
<script>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var vipList = [];
var DEFAULT_AVATAR_URL = "default.jpg";
//连接websocket TODO
var websocketURL = window.location.search.substring(7);
var socket = null;
//时钟
setInterval(function(){
	let now = new Date();
	let year = now.getFullYear();
	let month = now.getMonth() + 1;
	let date = now.getDate();
	let hour = now.getHours();
	if(hour < 10){
		hour = "0" + hour;
	}
	let minute = now.getMinutes();
	if(minute < 10){
		minute = "0" + minute;
	}
	let second = now.getSeconds();
	if(second < 10){
		second = "0" + second;
	}
	let nowDateStr = year + "年" + month + "月" + date + "日 " + hour + ":" + minute + ":" + second;
	document.getElementById("clock").innerText = nowDateStr;
	if(vue.switchTime && now > vue.switchTime){
		if(vue.exit == 0){
			vue.exit=1;
			vue.switchTime=null;
		}else if(vue.exit == 1){
			vue.exit=0;
			vue.switchTime=null;
			vue.startGame();
		}
	}
},1000);
//计时器
var timerInterval;
function timer(text,start,end){
	document.getElementById("timer-text").innerText=text;
	clearInterval(timerInterval);
	let time = start;
	function f(){
		document.getElementById("timer-time").innerText=time;
		if(time<0){
			document.getElementById("timer-ex").innerText="弹幕延迟补时";
		}else{
			document.getElementById("timer-ex").innerText="";
		}
		if(time>end){
			time--;
		}else if(time<end){
			time++;
		}else{
			clearInterval(timerInterval);
			if(text=="红方行棋"){
				vue.output("红方超时，黑方胜");
				vue.red_peace=2;
				vue.black_peace=1;
				vue.endGame();
			}else if(text=="黑方行棋"){
				vue.output("黑方超时，红方胜");
				vue.red_peace=1;
				vue.black_peace=2;
				vue.endGame();
			}else if(text=="游戏结束" && vue.exit==0){
				vue.startGame();
			}
		}
		if(time<=10&&(text=="红方行棋"||text=="黑方行棋")&&vue.send_addtime){
			vue.output("请注意右上角倒计时，时间不够可【加时】");
			vue.send_addtime=0;
		}
	}
	f();
	timerInterval = setInterval(f,1000);
}
var addTimeCount = 0; //加时次数
//加时
function addTime(color){
	let time = parseInt(document.getElementById("timer-time").innerText);
	let text = document.getElementById("timer-text").innerText;
	if(time > 30){
		vue.output((color==0?"红":"黑")+"方剩余时间不足30秒方可加时");
		return;
	}
	timer(text,time+60,-20);
	addTimeCount++;
	vue.output((color==0?"红":"黑")+"方已加时60秒");
}
//象棋棋子类定义
function Chess(color,type,locX,locY){
	this.color = color;
	this.type = type;
	this.locX = locX;
	this.locY = locY;
	var active = true;
	this.disActive = disActive;
	function disActive(){
		active = false;
	}
	this.isActive = isActive;
	function isActive(){
		return active;
	}
	this.getName = getName;
	function getName(){
		if(type=="ju"){
			return "車";
		}else if(type=="ma"){
			return "馬";
		}else if(type=="pao"){
			return "炮";
		}
		if(color==1){
			if(type=="xiang"){
				return "象";
			}else if(type=="shi"){
				return "士";
			}else if(type=="shuai"){
				return "將";
			}else if(type=="bing"){
				return "卒";
			}
		}else if(color==0){
			if(type=="xiang"){
				return "相";
			}else if(type=="shi"){
				return "仕";
			}else if(type=="shuai"){
				return "帥";
			}else if(type=="bing"){
				return "兵";
			}
		}
	}
}
//象棋类型定义
var chessTypes = ["ju","ma","xiang","shi","shuai","pao","bing"];
//象棋棋盘（及其上所有棋子定义）
function getChessGame(){
	return [new Chess(1,"ju",0,0), new Chess(1,"ma",1,0), 
		new Chess(1,"xiang",2,0),new Chess(1,"shi",3,0),
		new Chess(1,"shuai",4,0),new Chess(1,"shi",5,0),
		new Chess(1,"xiang",6,0),new Chess(1,"ma",7,0),
		new Chess(1,"ju",8,0),new Chess(1,"pao",1,2),
		new Chess(1,"pao",7,2),new Chess(1,"bing",0,3),
		new Chess(1,"bing",2,3),new Chess(1,"bing",4,3),
		new Chess(1,"bing",6,3),new Chess(1,"bing",8,3),
		new Chess(0,"ju",0,9), new Chess(0,"ma",1,9), 
		new Chess(0,"xiang",2,9),new Chess(0,"shi",3,9),
		new Chess(0,"shuai",4,9),new Chess(0,"shi",5,9),
		new Chess(0,"xiang",6,9),new Chess(0,"ma",7,9),
		new Chess(0,"ju",8,9),new Chess(0,"pao",1,7),
		new Chess(0,"pao",7,7),new Chess(0,"bing",0,6),
		new Chess(0,"bing",2,6),new Chess(0,"bing",4,6),
		new Chess(0,"bing",6,6),new Chess(0,"bing",8,6)];
}
var chessGame;
var currentX,currentY;
var previousX,previousY;
//根据象棋类型的中文获取对应的象棋类型枚举
function getChessType(chessTypeName){
	if(chessTypeName == '车' || chessTypeName == '車'){
		return "ju";
	}else if(chessTypeName == '马' || chessTypeName == '馬'){
		return "ma";
	}else if(chessTypeName == '相' || chessTypeName == '象'){
		return "xiang";
	}else if(chessTypeName == '士' || chessTypeName == '仕'){
		return "shi";
	}else if(chessTypeName == '帅' || chessTypeName == '帥' || chessTypeName == '将' || chessTypeName == '將'){
		return "shuai";
	}else if(chessTypeName == '炮' || chessTypeName == '砲'){
		return "pao";
	}else if(chessTypeName == '兵' || chessTypeName == '卒'){
		return "bing";
	}
}
//根据象棋类型枚举获取对应的象棋类型中文（简体）
function getChessName(chessType, color){
	if(chessType=="ju"){
		return "车";
	}else if(chessType=="ma"){
		return "马";
	}else if(chessType=="pao"){
		return "炮";
	}
	if(color==1){
		if(chessType=="xiang"){
			return "象";
		}else if(chessType=="shi"){
			return "士";
		}else if(chessType=="shuai"){
			return "将";
		}else if(chessType=="bing"){
			return "卒";
		}
	}else if(color==0){
		if(chessType=="xiang"){
			return "相";
		}else if(chessType=="shi"){
			return "仕";
		}else if(chessType=="shuai"){
			return "帅";
		}else if(chessType=="bing"){
			return "兵";
		}
	}
}
//根据象棋类型、相对位置和红黑方获取符合条件的象棋棋子
function getChessFromRelativeLoc(chessType,relativeLoc,color){
	let chesses = [];
	//首先获取符合象棋类型和红黑方条件的棋子
	for(let i=0;i<chessGame.length;i++){
		if(chessGame[i].isActive() && chessType == chessGame[i].type && color == chessGame[i].color){
			chesses.push(chessGame[i]);
		}
	}
	//无符合象棋类型和红黑方条件的棋子直接返回
	if(!chesses){
		return "找不到棋子“" + getChessName(chessType,color) + "”";
	//对于“前”、“后”开头的行棋语句且两棋子位于同一列则返回对应在前或在后棋子
	}else if(relativeLoc == -2 || relativeLoc == -1){
		if(chesses.length < 2){
			return "不存在同一列上的两个相同棋子“" + getChessName(chessType,color) + "”，<br>请不要使用“前”或“后”开头";
		}
		let chess1;
		let chess2;
		for(let i=0;i<chesses.length;i++){
			for(let j=i+1;j<chesses.length;j++){
				if(chesses[i].locX == chesses[j].locX){
					chess1 = chesses[i];
					chess2 = chesses[j];
				}
			}
		}
		if(!chess1){
			return "不存在同一列上的两个相同棋子“" + getChessName(chessType,color) + "”，<br>请不要使用“前”或“后”开头";
		}
		if(relativeLoc == -1){
			if(color == 0){
				if(chess1.locY < chess2.locY){
					return chess1;
				}else if(chess1.locY > chess2.locY){
					return chess2;
				}
			}else if(color == 1){
				if(chess1.locY < chess2.locY){
					return chess2;
				}else if(chess1.locY > chess2.locY){
					return chess1;
				}
			}
		}else if(relativeLoc == -2){
			if(color == 0){
				if(chess1.locY < chess2.locY){
					return chess2;
				}else if(chess1.locY > chess2.locY){
					return chess1;
				}
			}else if(color == 1){
				if(chess1.locY < chess2.locY){
					return chess1;
				}else if(chess1.locY > chess2.locY){
					return chess2;
				}
			}
		}
	//对于普通的行棋语句则返回对应列上唯一的棋子
	}else{
		let returnChess = "对应列上无棋子“" + getChessName(chessType,color) + "”";
		for(let i=0;i<chesses.length;i++){
			let chess = chesses[i];
			if(color == 0){
				if(chess.locX == 9-relativeLoc){
					if(typeof returnChess == "string"){
						returnChess = chess;
					}else{
						return "对应列上有两个棋子“" + getChessName(chessType,color) + "”，<br>请使用“前”或“后”开头";
					}
				}
			}else if(color == 1){
				if(chess.locX == relativeLoc-1){
					if(typeof returnChess == "string"){
						returnChess = chess;
					}else{
						return "对应列上有两个棋子“" + getChessName(chessType,color) + "”，<br>请使用“前”或“后”开头";
					}
				}
			}
		}
		return returnChess;
	}
}
//根据坐标获取棋子
function getChessFromLoc(locX,locY){
	for(let i=0;i<chessGame.length;i++){
		if(chessGame[i].isActive() && chessGame[i].locX == locX && chessGame[i].locY == locY){
			return chessGame[i];
		}
	}
}
//移动棋子到指定方向和地点，成功返回空，失败返回提示信息
function moveChess(chess,direction,dest){
	let destX;
	let destY;
	if(chess.type == "ju"){
		if(chess.color == 0){
			if(direction == 1){
				destX = chess.locX;
				destY = chess.locY - dest;
			}else if(direction == 0){
				destX = 9-dest;
				destY = chess.locY;
			}else if(direction == -1){
				destX = chess.locX;
				destY = chess.locY + dest;
			}
		}else if(chess.color == 1){
			if(direction == 1){
				destX = chess.locX;
				destY = chess.locY + dest;
			}else if(direction == 0){
				destX = dest-1;
				destY = chess.locY;
			}else if(direction == -1){
				destX = chess.locX;
				destY = chess.locY - dest;
			}
		}
		if(destX < 0 || destX > 8 || destY < 0 || destY > 9){
			return "超出棋盘范围";
		}
		if(destX == chess.locX && destY == chess.locY){
			return "棋子没有移动";
		}
		let startX = destX < chess.locX ? destX : chess.locX;
		let startY = destY < chess.locY ? destY : chess.locY;
		let endX = destX < chess.locX ? chess.locX : destX;
		let endY = destY < chess.locY ? chess.locY : destY;
		for(let x=startX; x<=endX; x++){
			for(let y=startY; y<=endY; y++){
				if((x != chess.locX || y != chess.locY) && (x != destX || y != destY)){
					let chessPath = getChessFromLoc(x,y);
					if(chessPath){
						return "车的移动路径上有棋子阻挡";
					}
				}
				
			}
		}
		let chessDest = getChessFromLoc(destX,destY);
		if(chessDest){
			if(chessDest.color != chess.color){
				chessDest.disActive();
			}else if(chessDest.color == chess.color){
				return "目的地有己方棋子阻挡";
			}
		}
	}else if(chess.type == "ma"){
		if(chess.color == 0){
			if(direction == 1){
				destX = 9-dest;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY - 2;
				}else if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY - 1;
				}else{
					return "马无法走到对应列";
				}
			}else if(direction == 0){
				return "马不能平走";
			}else if(direction == -1){
				destX = 9-dest;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY + 2;
				}else if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY + 1;
				}else{
					return "马无法走到对应列";
				}
			}
		}else if(chess.color == 1){
			if(direction == 1){
				destX = dest-1;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY + 2;
				}else if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY + 1;
				}else{
					return "马无法走到对应列";
				}
			}else if(direction == 0){
				return "马不能平走";
			}else if(direction == -1){
				destX = dest-1;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY - 2;
				}else if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY - 1;
				}else{
					return "马无法走到对应列";
				}
			}
		}
		if(destX < 0 || destX > 8 || destY < 0 || destY > 9){
			return "超出棋盘范围";
		}
		let middleX;
		let middleY;
		if(chess.locX - destX == 1 || chess.locX - destX == -1){
			middleX = chess.locX;
		}else if(chess.locX - destX == 2 || chess.locX - destX == -2){
			middleX = (chess.locX + destX) / 2;
		}
		if(chess.locY - destY == 1 || chess.locY - destY == -1){
			middleY = chess.locY;
		}else if(chess.locY - destY == 2 || chess.locY - destY == -2){
			middleY = (chess.locY + destY) / 2;
		}
		let chessMiddle = getChessFromLoc(middleX,middleY);
		if(chessMiddle){
			return "撇马腿";
		}
		let chessDest = getChessFromLoc(destX,destY);
		if(chessDest){
			if(chessDest.color != chess.color){
				chessDest.disActive();
			}else if(chessDest.color == chess.color){
				return "目的地有己方棋子阻挡";
			}
		}
	}else if(chess.type == "pao"){
		if(chess.color == 0){
			if(direction == 1){
				destX = chess.locX;
				destY = chess.locY - dest;
			}else if(direction == 0){
				destX = 9-dest;
				destY = chess.locY;
			}else if(direction == -1){
				destX = chess.locX;
				destY = chess.locY + dest;
			}
		}else if(chess.color == 1){
			if(direction == 1){
				destX = chess.locX;
				destY = chess.locY + dest;
			}else if(direction == 0){
				destX = dest-1;
				destY = chess.locY;
			}else if(direction == -1){
				destX = chess.locX;
				destY = chess.locY - dest;
			}
		}
		if(destX < 0 || destX > 8 || destY < 0 || destY > 9){
			return "超出棋盘范围";
		}
		if(destX == chess.locX && destY == chess.locY){
			return "棋子没有移动";
		}
		let startX = destX < chess.locX ? destX : chess.locX;
		let startY = destY < chess.locY ? destY : chess.locY;
		let endX = destX < chess.locX ? chess.locX : destX;
		let endY = destY < chess.locY ? chess.locY : destY;
		let chessPathCount = 0;
		for(let x=startX; x<=endX; x++){
			for(let y=startY; y<=endY; y++){
				if((x != chess.locX || y != chess.locY) && (x != destX || y != destY)){
					let chessPath = getChessFromLoc(x,y);
					if(chessPath){
						chessPathCount++;
					}
				}
				
			}
		}
		let chessDest = getChessFromLoc(destX,destY);
		if(chessPathCount == 0){
			if(chessDest){
				return "目的地有棋子阻挡";
			}
		}else if(chessPathCount == 1){
			if(chessDest){
				if(chessDest.color != chess.color){
					chessDest.disActive();
				}else if(chessDest.color == chess.color){
					return "目的地有己方棋子阻挡";
				}
			}else{
				return "炮的目的地无棋子且移动路径上有棋子";
			}
		}else{
			return "炮的移动路径上有两个或以上的棋子";
		}
	}else if(chess.type == "bing"){
		if(chess.color == 0){
			if(direction == 1){
				if(dest == 1){
					destX = chess.locX;
					destY = chess.locY - dest;
				}else{
					return "兵只能前进一格";
				}
			}else if(direction == 0){
				if(chess.locY <= 4){
					destX = 9-dest;
					destY = chess.locY;
				}else{
					return "未过河的兵不能平走";
				}
			}else if(direction == -1){
				return "兵不能后退";
			}
		}else if(chess.color == 1){
			if(direction == 1){
				if(dest == 1){
					destX = chess.locX;
					destY = chess.locY + dest;
				}else{
					return "卒只能前进一格";
				}
			}else if(direction == 0){
				if(chess.locY >= 5){
					destX = dest-1;
					destY = chess.locY;
				}else{
					return "未过河的卒不能平走";
				}
			}else if(direction == -1){
				return "卒不能后退";
			}
		}
		if(destX < 0 || destX > 8 || destY < 0 || destY > 9){
			return "超出棋盘范围";
		}
		if(destX == chess.locX && destY == chess.locY){
			return "棋子没有移动";
		}
		if(destX - chess.locX >= 2 || destX - chess.locX <= -2){
			return "兵(卒)只能平移一格";
		}
		let chessDest = getChessFromLoc(destX,destY);
		if(chessDest){
			if(chessDest.color != chess.color){
				chessDest.disActive();
			}else if(chessDest.color == chess.color){
				return "目的地有己方棋子阻挡";
			}
		}
	}else if(chess.type == "xiang"){
		if(chess.color == 0){
			if(direction == 1){
				destX = 9-dest;
				if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY - 2;
				}else{
					return "相无法走到对应列";
				}
			}else if(direction == 0){
				return "相不能平走";
			}else if(direction == -1){
				destX = 9-dest;
				if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY + 2;
				}else{
					return "相无法走到对应列";
				}
			}
			if(destY <= 4){
				return "相不能过河";
			}
		}else if(chess.color == 1){
			if(direction == 1){
				destX = dest-1;
				if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY + 2;
				}else{
					return "象无法走到对应列";
				}
			}else if(direction == 0){
				return "象不能平走";
			}else if(direction == -1){
				destX = dest-1;
				if(chess.locX - destX == 2 || chess.locX - destX == -2){
					destY = chess.locY - 2;
				}else{
					return "象无法走到对应列";
				}
			}
			if(destY >= 5){
				return "象不能过河";
			}
		}
		if(destX < 0 || destX > 8 || destY < 0 || destY > 9){
			return "超出棋盘范围";
		}
		let middleX = (chess.locX + destX) / 2;
		let middleY = (chess.locY + destY) / 2;
		let chessMiddle = getChessFromLoc(middleX,middleY);
		if(chessMiddle){
			return "塞象眼";
		}
		let chessDest = getChessFromLoc(destX,destY);
		if(chessDest){
			if(chessDest.color != chess.color){
				chessDest.disActive();
			}else if(chessDest.color == chess.color){
				return "目的地有己方棋子阻挡";
			}
		}
	}else if(chess.type == "shi"){
		if(chess.color == 0){
			if(direction == 1){
				destX = 9-dest;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY - 1;
				}else{
					return "仕无法走到对应列";
				}
			}else if(direction == 0){
				return "仕不能平走";
			}else if(direction == -1){
				destX = 9-dest;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY + 1;
				}else{
					return "仕无法走到对应列";
				}
			}
			if(destY <= 6 || destY >= 10 || destX <= 2 || destX >= 6){
				return "仕不能走出九宫";
			}
		}else if(chess.color == 1){
			if(direction == 1){
				destX = dest-1;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY + 1;
				}else{
					return "士无法走到对应列";
				}
			}else if(direction == 0){
				return "士不能平走";
			}else if(direction == -1){
				destX = dest-1;
				if(chess.locX - destX == 1 || chess.locX - destX == -1){
					destY = chess.locY - 1;
				}else{
					return "士无法走到对应列";
				}
			}
			if(destY <= -1 || destY >= 3 || destX <= 2 || destX >= 6){
				return "士不能走出九宫";
			}
		}
		let chessDest = getChessFromLoc(destX,destY);
		if(chessDest){
			if(chessDest.color != chess.color){
				chessDest.disActive();
			}else if(chessDest.color == chess.color){
				return "目的地有己方棋子阻挡";
			}
		}
	}else if(chess.type == "shuai"){
		if(chess.color == 0){
			if(direction == 1){
				if(dest == 1){
					destX = chess.locX;
					destY = chess.locY - dest;
				}else{
					return "帅只能前进一格";
				}
			}else if(direction == 0){
				destX = 9-dest;
				destY = chess.locY;
			}else if(direction == -1){
				if(dest == 1){
					destX = chess.locX;
					destY = chess.locY + dest;
				}else{
					return "帅只能后退一格";
				}
			}
			if(destY <= 6 || destY >= 10 || destX <= 2 || destX >= 6){
				return "帅不能走出九宫";
			}
		}else if(chess.color == 1){
			if(direction == 1){
				if(dest == 1){
					destX = chess.locX;
					destY = chess.locY + dest;
				}else{
					return "将只能前进一格";
				}
			}else if(direction == 0){
				destX = dest-1;
				destY = chess.locY;
			}else if(direction == -1){
				if(dest == 1){
					destX = chess.locX;
					destY = chess.locY - dest;
				}else{
					return "将只能后退一格";
				}
			}
			if(destY <= -1 || destY >= 3 || destX <= 2 || destX >= 6){
				return "将不能走出九宫";
			}
		}
		if(destX == chess.locX && destY == chess.locY){
			return "棋子没有移动";
		}
		if(destX - chess.locX >= 2 || destX - chess.locX <= -2){
			return "帅(将)只能平移一格";
		}
		let chessDest = getChessFromLoc(destX,destY);
		if(chessDest){
			if(chessDest.color != chess.color){
				chessDest.disActive();
			}else if(chessDest.color == chess.color){
				return "目的地有己方棋子阻挡";
			}
		}
	}
	previousX = chess.locX;
	previousY = chess.locY;
	currentX = destX;
	currentY = destY;
	chess.locX = destX;
	chess.locY = destY;
}
//检查游戏是否结束以及哪一方获胜
function checkEnd(color){
	let chessShuai;
	let chessJiang;
	for(let i=0;i<chessGame.length;i++){
		if(chessGame[i].isActive() && chessGame[i].type == "shuai"){
			if(chessGame[i].color == 0){
				chessShuai = chessGame[i];
			}else if(chessGame[i].color == 1){
				chessJiang = chessGame[i];
			}
		}
	}
	//哪一方将（帅）没了则另一方获胜
	if(!chessShuai){
		return 1;
	}else if(!chessJiang){
		return 0;
	}else{
		if(chessShuai.locX == chessJiang.locX){
			let x = chessShuai.locX;
			for(let y=chessJiang.locY+1; y<=chessShuai.locY-1; y++){
				let chessPath = getChessFromLoc(x,y);
				if(chessPath){
					return -1;
				}
			}
			//如果将帅照面则行棋方失败
			if(color == 0){
				return 1;
			}else if(color == 1){
				return 0;
			}
		}else{
			return -1;
		}
	}
}
//中文数字转阿拉伯数字
function toArabicNum(chineseNum){
	if(chineseNum == '一' || chineseNum == '1'){
		return 1;
	}else if(chineseNum == '二' || chineseNum == '2'){
		return 2;
	}else if(chineseNum == '三' || chineseNum == '3'){
		return 3;
	}else if(chineseNum == '四' || chineseNum == '4'){
		return 4;
	}else if(chineseNum == '五' || chineseNum == '5'){
		return 5;
	}else if(chineseNum == '六' || chineseNum == '6'){
		return 6;
	}else if(chineseNum == '七' || chineseNum == '7'){
		return 7;
	}else if(chineseNum == '八' || chineseNum == '8'){
		return 8;
	}else if(chineseNum == '九' || chineseNum == '9'){
		return 9;
	}else{
		return;
	}
}
//阿拉伯数字转中文数字
function toChineseNum(arabicNum){
	if(arabicNum == 1){
		return "一";
	}else if(arabicNum == 2){
		return "二";
	}else if(arabicNum == 3){
		return "三";
	}else if(arabicNum == 4){
		return "四";
	}else if(arabicNum == 5){
		return "五";
	}else if(arabicNum == 6){
		return "六";
	}else if(arabicNum == 7){
		return "七";
	}else if(arabicNum == 8){
		return "八";
	}else if(arabicNum == 9){
		return "九";
	}else{
		return;
	}
}
//行棋方法，入参为行棋语句及红黑方，返回为行棋结果
function step(input0,color){
	//限制行棋语句为4个字
	if(input0.length != 4){
		return;
	}
	//为防屏蔽词，允许“平九炮八”的前后颠倒写法
	let input;
	if(input0.charAt(0) == '进' || input0.charAt(0) == '進' || input0.charAt(0) == '退' || input0.charAt(0) == '平'){
		input = input0.substring(2,4) + input0.substring(0,2);
	}else{
		input = input0;
	}
	let chessType;
	let relativeLoc;
	let inputResult = "";
	//对于“前”、“后”开头的行棋语句处理
	if(input.charAt(0) == '前' || input.charAt(0) == '后' || input.charAt(0) == '後'){
		//从第二个字获取象棋类型
		chessType = getChessType(input.charAt(1));
		//从第一个字获取相对位置，前为-1，后为-2
		if(input.charAt(0) == '前'){
			relativeLoc = -1;
			inputResult += "前";
		}else{
			relativeLoc = -2;
			inputResult += "后";
		}
		inputResult += getChessName(chessType, color);
	//对于普通的行棋语句处理
	}else{
		//从第一个字获取象棋类型
		chessType = getChessType(input.charAt(0));
		inputResult += getChessName(chessType, color);
		//从第二个字获取相对位置
		relativeLoc = toArabicNum(input.charAt(1));
		if(!relativeLoc){
			return;
		}
		if(color == 0){
			inputResult += toChineseNum(relativeLoc);
		}else if(color == 1){
			inputResult += relativeLoc;
		}
	}
	if(!chessType){
		return;
	}
	//获取行棋语句指定要移动的象棋棋子
	let chess = getChessFromRelativeLoc(chessType,relativeLoc,color);
	if(typeof chess == "string" && chess.substring(0,9) == "对应列上有两个棋子"){
		//针对象或士位于同一列的情况
		if(chessType == 'xiang' || chessType == 'shi'){
			if(input.charAt(2) == '进' || input.charAt(2) == '進'){
				relativeLoc = -2;
			}else if(input.charAt(2) == '退'){
				relativeLoc = -1;
			}
			chess = getChessFromRelativeLoc(chessType,relativeLoc,color);
		}
	}
	//从第三个字获取棋子的移动方向
	let direction;
	if(input.charAt(2) == '进' || input.charAt(2) == '進'){
		direction = 1;
		inputResult += "进";
	}else if(input.charAt(2) == '平'){
		direction = 0;
		inputResult += "平";
	}else if(input.charAt(2) == '退'){
		direction = -1;
		inputResult += "退";
	}else{
		return;
	}
	//从第四个字获取棋子的移动目标
	let dest = toArabicNum(input.charAt(3));
	if(!dest){
		return;
	}
	if(color == 0){
		inputResult += toChineseNum(dest);
	}else if(color == 1){
		inputResult += dest;
	}
	//对可能合法但无法找到需要移动棋子的行棋语句进行提示
	if(typeof chess == "string"){
		vue.output("【"+input0+"】NO，请重新输入行棋语句");
		vue.$message({
			message:"【"+inputResult+"】<br>"+chess,
			duration:10000,
			type:"error",
			dangerouslyUseHTMLString:true
		});
		return;
	}
	//获取棋子移动结果，为空则正常移动，否则移动失败
	let result = moveChess(chess,direction,dest);
	if(result){
		vue.output("【"+input0+"】NO，请重新输入行棋语句");
		vue.$message({
			message:"【"+inputResult+"】<br>"+result,
			duration:10000,
			type:"error",
			dangerouslyUseHTMLString:true
		});
		return;
	}
	//棋子移动后重画棋盘和棋子
	drawChessGame();
	if(checkEnd(color) == 0){
		vue.output("【"+input0+"】OK，红方胜");
		vue.red_peace=1;
		vue.black_peace=2;
		vue.endGame();
	}else if(checkEnd(color) == 1){
		vue.output("【"+input0+"】OK，黑方胜");
		vue.red_peace=2;
		vue.black_peace=1;
		vue.endGame();
	}else if(checkEnd(color) == -1){
		vue.output("【"+input0+"】OK，请"+(color==0?"黑":"红")+"方行棋");
		timer((color==0?"黑":"红")+"方行棋",60,-20);
	}
	return inputResult;
}
//是否处于屏蔽词测试模式
var inTestWord;
var blockedWordsArr = [];//被屏蔽的行棋语句列表
var passedWordsArr = [];//没有被屏蔽的行棋语句列表
//获取一个合法的行棋语句以供测试
function getTestWord(stepNum){
	let chessType = chessTypes[Math.floor(Math.random()*7)];
	let relativeLoc = Math.floor(Math.random()*11)-1;
	let directionSet = ["进","退","平"];
	let direction = directionSet[Math.floor(Math.random()*3)];
	let dest = Math.floor(Math.random()*9)+1;
	let testResult = "";
	if(chessType == "ma"){
		if(direction == "平"){//马不能平走
			return false;
		}
		if(relativeLoc > 0 && dest - relativeLoc != 2 && dest - relativeLoc != 1 
				&& dest - relativeLoc != -1 && dest - relativeLoc != -2){//马的目标列与起始列差值只能为2、1、-1、-2
			return false;
		}
	}else if(chessType == "xiang"){
		if(direction == "平"){//象不能平走
			return false;
		}
		if(relativeLoc != 1 && relativeLoc != 3 && relativeLoc != 5 
				&& relativeLoc != 7 && relativeLoc != 9){//象的起始列只能是1、3、5、7、9
			return false;
		}
		if(dest != 1 && dest != 3 && dest != 5 && dest != 7 && dest != 9){//象的目标列只能是1、3、5、7、9
			return false;
		}
		if(dest - relativeLoc != 2 && dest - relativeLoc != -2){//象的目标列与起始列差值只能为2或-2
			return false;
		}
	}else if(chessType == "shi"){
		if(direction == "平"){//士不能平走
			return false;
		}
		if(relativeLoc != 4 && relativeLoc != 5 && relativeLoc != 6){//士的起始列只能是4、5、6
			return false;
		}
		if(dest != 4 && dest != 5 && dest != 6){//士的目标列只能是4、5、6
			return false;
		}
		if(dest - relativeLoc != 1 && dest - relativeLoc != -1){//士的目标列与起始列差值只能为1或-1
			return false;
		}
	}else if(chessType == "shuai"){
		if(relativeLoc != 4 && relativeLoc != 5 && relativeLoc != 6){//帅的起始列只能是4、5、6
			return false;
		}
		if(direction == "平"){
			if(dest != 4 && dest != 5 && dest != 6){//帅平走时的目标列只能是4、5、6
				return false;
			}
			if(dest - relativeLoc != 1 && dest - relativeLoc != -1){//帅平走时目标列与起始列差值只能为1或-1
				return false;
			}
		}else{
			if(dest != 1){//帅前进或后退时只能走一步
				return false;
			}
		}		
	}else if(chessType == "bing"){
		if(direction == "退"){//兵不能后退
			return false;
		}else if(direction == "平"){//兵平走时目标列与起始列差值只能为1或-1
			if(relativeLoc > 0 && dest - relativeLoc != 1 && dest - relativeLoc != -1){
				return false;
			}
		}else{
			if(dest != 1){//兵前进时只能走一步
				return false;
			}
		}
	}else if(direction == "平" && relativeLoc == dest){//车和炮平走时目标列与起始列不能相同
		return false;
	}
	if(relativeLoc == -1){
		testResult += "前";
	}else if(relativeLoc == 0){
		testResult += "后";
	}
	testResult += getChessName(chessType, (stepNum+1) % 2);
	if(relativeLoc > 0){
		testResult += (stepNum % 2) ? toChineseNum(relativeLoc) : relativeLoc;
	}
	testResult += direction;
	testResult += (stepNum % 2) ? toChineseNum(dest) : dest;
	return testResult;
}
//画布定义
var scale = 60;
var radius = 25;
//画棋盘
function drawChessPlate(){
	context.beginPath();
	context.lineWidth="1";
	context.strokeStyle="black";
	context.moveTo(scale,scale);
	context.lineTo(scale*9,scale);
	context.lineTo(scale*9,scale*10);
	context.lineTo(scale,scale*10);
	context.lineTo(scale,scale);
	for(let i=2;i<=9;i++){
		context.moveTo(scale,scale*i);
		context.lineTo(scale*9,scale*i);
	}
	for(let i=2;i<=8;i++){
		context.moveTo(scale*i,scale);
		context.lineTo(scale*i,scale*5);
	}
	for(let i=2;i<=8;i++){
		context.moveTo(scale*i,scale*6);
		context.lineTo(scale*i,scale*10);
	}
	context.moveTo(scale*4,scale);
	context.lineTo(scale*6,scale*3);
	context.moveTo(scale*6,scale);
	context.lineTo(scale*4,scale*3);
	context.moveTo(scale*4,scale*8);
	context.lineTo(scale*6,scale*10);
	context.moveTo(scale*6,scale*8);
	context.lineTo(scale*4,scale*10);
	function drawCross(context,x,y){
		if(x!=1){
			context.moveTo(scale*x-20,scale*y-5);
			context.lineTo(scale*x-5,scale*y-5);
			context.lineTo(scale*x-5,scale*y-20);
			context.moveTo(scale*x-20,scale*y+5);
			context.lineTo(scale*x-5,scale*y+5);
			context.lineTo(scale*x-5,scale*y+20);
		}
		if(x!=9){
			context.moveTo(scale*x+20,scale*y-5);
			context.lineTo(scale*x+5,scale*y-5);
			context.lineTo(scale*x+5,scale*y-20);
			context.moveTo(scale*x+20,scale*y+5);
			context.lineTo(scale*x+5,scale*y+5);
			context.lineTo(scale*x+5,scale*y+20);
		}
	}
	drawCross(context,2,3);
	drawCross(context,8,3);
	drawCross(context,1,4);
	drawCross(context,3,4);
	drawCross(context,5,4);
	drawCross(context,7,4);
	drawCross(context,9,4);
	drawCross(context,1,7);
	drawCross(context,3,7);
	drawCross(context,5,7);
	drawCross(context,7,7);
	drawCross(context,9,7);
	drawCross(context,2,8);
	drawCross(context,8,8);
	context.stroke();
}
//画棋子
function drawChess(context,chess){
	context.beginPath();
	context.lineWidth="1";
	context.strokeStyle="black";
	context.arc(scale*(chess.locX+1),scale*(chess.locY+1),radius,0,2*Math.PI);
	context.stroke();
	context.fillStyle=chess.color==0?"yellow":"black";
	context.fill();
	context.textAlign="center";
	context.fillStyle=chess.color==0?"red":"white";
	context.font="30px normal";
	context.fillText(chess.getName(),scale*(chess.locX+1),scale*(chess.locY+1)+11);
}
//画出刚刚移动的棋子的外框
function drawBox(locX,locY){
	context.beginPath();
	context.lineWidth="1";
	context.strokeStyle="red";
	context.moveTo(scale*(locX+1)-27,scale*(locY+1)-17);
	context.lineTo(scale*(locX+1)-27,scale*(locY+1)-27);
	context.lineTo(scale*(locX+1)-17,scale*(locY+1)-27);
	context.moveTo(scale*(locX+1)-27,scale*(locY+1)+17);
	context.lineTo(scale*(locX+1)-27,scale*(locY+1)+27);
	context.lineTo(scale*(locX+1)-17,scale*(locY+1)+27);
	context.moveTo(scale*(locX+1)+27,scale*(locY+1)-17);
	context.lineTo(scale*(locX+1)+27,scale*(locY+1)-27);
	context.lineTo(scale*(locX+1)+17,scale*(locY+1)-27);
	context.moveTo(scale*(locX+1)+27,scale*(locY+1)+17);
	context.lineTo(scale*(locX+1)+27,scale*(locY+1)+27);
	context.lineTo(scale*(locX+1)+17,scale*(locY+1)+27);
	context.stroke();
}
//画出完整的棋局（包括棋盘和所有棋子）
function drawChessGame(){
	context.clearRect(0,0,canvas.width,canvas.height);
	drawChessPlate();
	for(let i=0;i<chessGame.length;i++){
		if(chessGame[i].isActive()){
			drawChess(context,chessGame[i]);
		}
	}
	if(previousX!=null){
		drawBox(previousX,previousY);
		drawBox(currentX,currentY);
	}
}
//管理员命令
var adminCommands = [];
//vue框架相关
var vue = new Vue({
	el: "#app",
	data: {
		exit: 1, //0正常游戏，1停止游戏
		switchTime: null, //停止或恢复游戏时间
		status: 0, //游戏状态，0准备游戏，1游戏中
		start_count: 0, //连续开始次数
		step_count: 0, //对局中下棋步数
		send_addtime: 1, //是否发送加时提醒，1待发送，0已发送
		color: 0, //执棋方，0红方执棋，1黑方执棋（准备状态此标志无效）
		red_rival_name: "~~刚刚开播~~", //红方选手名
		black_rival_name: "~~等待启动~~", //黑方选手名
		red_image: DEFAULT_AVATAR_URL, //红方头像
		black_image: DEFAULT_AVATAR_URL, //黑方头像
		red_peace: 0, //红方获胜状态，0其他，1胜，2败，3和棋
		black_peace: 0, //黑方获胜状态，0其他，1胜，2败，3和棋
		recentdm: null, //除主播和房管外最近弹幕发送时间
		recentgame: null, //最近对局结束时间
		logs: [], //行棋记录(step, content)
		queue: [], //排队队列(point, name, ready)
		donators: [], //送礼但未排队用户(name, point)
		images: [], //用户头像(username, image)
		messages: [] //留言板(name, text)
	},
	methods: {
		//行棋方法，行棋并记录行棋日志
		onStep: function(input,color){
			if(input=="加时"||input=="加時"){
				if(addTimeCount<2){
					addTime(color);
					return;
				}else{
					vue.output((color==0?"红":"黑")+"方本轮加时次数已用完");
					return;
				}
			}
			let stepResult = step(input,color);
			if(stepResult){
				vue.step_count++;
				vue.logs.push({"step":vue.step_count,"content":stepResult});
				if(vue.logs.length > 26){
					vue.logs.shift();
					vue.logs.shift();
				}
				vue.color=color==0?1:0;
				addTimeCount=0;
			}
		},
		//棋局结束后，重新准备新一局游戏
		endGame: function(){
			timer("游戏结束",20,0);
			vue.status=0;
			vue.start_count=0;
			vue.recentgame=new Date();
		},
		//准备就绪后，开始游戏
		startGame: function(){
			vue.testWordEnd();
			chessGame = getChessGame();
			currentX=null,currentY=null;
			previousX=null,previousY=null;
			drawChessGame();
			vue.status=0;
			vue.logs=[];
			vue.red_rival_name="~~欢迎各位~~";
			vue.black_rival_name="~~参与游戏~~";
			vue.red_peace=0;
			vue.black_peace=0;
			vue.send_addtime=1;
			vue.step_count=0;
			if(vue.start_count<12){
				switch(vue.start_count%3){
				case 0:
					vue.output("队列中玩家请【准备】，其他玩家请【排队】");
					break;
				case 1:
					vue.output("新玩家参与游戏，请先【排队】再【准备】");
					break;
				case 2:
					if(vue.start_count%2==0){
						vue.output("关注【颜姬Channel】，欢迎下次再来");
					}else{
						vue.output("欢迎分享本直播间，和更多人一起玩");
					}
					break;
				}
			}else{
				switch(vue.start_count%30){
				case 12:
					vue.output("当前玩家较少，请耐心等待下一位玩家准备");
					break;
				case 18:
					vue.output("新玩家参与游戏，请先【排队】再【准备】");
					break;
				case 24:
					vue.output("队列中玩家请【准备】，其他玩家请【排队】");
					break;
				case 0:
					vue.output("关注【颜姬Channel】，欢迎下次再来");
					break;
				case 6:
					vue.output("欢迎分享本直播间，和更多人一起玩");
					break;
				}
			}
			vue.start_count++;
			timer("玩家准备",30,0);
			setTimeout(function(){
				let i=0,j=0,k=0,l=0;
				//队列中无玩家时再等30秒
				if(vue.queue==null&&vue.exit==0){
					vue.startGame();
					return;
				}
				for(i=0;i<vue.queue.length;i++){
					for(j=i+1;j<vue.queue.length;j++){
						if(vue.queue[i].ready && vue.queue[j].ready){
							//有两人或以上准备时开始游戏
							vue.red_rival_name=vue.queue[i].name;
							vue.black_rival_name=vue.queue[j].name;
							vue.red_image=vue.getImage(vue.queue[i].name);
							vue.black_image=vue.getImage(vue.queue[j].name);
							vue.status=1;
							vue.color=0;
							vue.output("棋局开始，请红方行棋，如【炮二平五】");
							timer("红方行棋",60,-20);
							addTimeCount=0;
							//从队列中移除参加游戏的人，和没有准备的0点（免费）玩家
							for(k=vue.queue.length-1;k>=0;k--){
								if(k==i||k==j||(k<=j&&vue.queue[k].point<=0)){
									for(l=k;l<vue.queue.length-1;l++){
										vue.queue[l]=vue.queue[l+1];
									}
									vue.queue.pop();
								}else{
									//清除其余玩家的准备状态
									vue.queue[k].ready=0;
								}
							}
							return;
						}
					}
				}
				//准备人数不足2人时再等30秒，并削弱已准备玩家的准备状态
				if(i==vue.queue.length){
					for(j=0;j<vue.queue.length;j++){
						if(vue.queue[j].ready>0){
							vue.queue[j].ready-=1;
						}
					}
					if(vue.exit==0){
						vue.startGame();
					}
				}
			}, 30000);//30秒后判断队列中准备的玩家人数
		},
		//排队
		addQueue: function(username,point){
			//停止游戏后不能再排队
			if(vue.exit==1){
				return;
			}
			let i=0,j=0,k=0;
			//检查排队用户是否在隐藏的送礼用户中
			for(i=0;i<vue.donators.length;i++){
				if(vue.donators[i].username==username){
					point+=vue.donators[i].point;
					vue.donators[i].point=0;
					break;
				}
			}
			for(i=0;i<vue.queue.length;i++){
				if(vue.queue[i].name==username){
					vue.queue[i].point+=point;
					break;
				}
			}
			if(i==vue.queue.length){
				vue.queue.push({"point":point,"name":username,"ready":0});
			}
			for(i=0;i<vue.queue.length;i++){
				for(j=i+1;j<vue.queue.length;j++){
					if(vue.queue[i].point<vue.queue[j].point){
						let t=vue.queue[j];
						for(k=j-1;k>=i;k--){
							vue.queue[k+1]=vue.queue[k];
						}
						vue.queue[i]=t;
						return;
					}
				}
			}
		},
		//退出排队
		removeQueue: function(username){
			function isIntLt100(a){
				return (!isNaN(a)) && a > 0 && a < 100 && a % 1 == 0;
			}
			let i=0,j=0;
			if(isIntLt100(username)){
				i = username - 1;
			}else{
				for(i=0;i<vue.queue.length;i++){
					if(vue.queue[i].name==username){
						break;
					}
				}
			}
			if(i<vue.queue.length){
				for(j=i;j<vue.queue.length-1;j++){
					vue.queue[j]=vue.queue[j+1];
				}
				vue.queue.pop();
			}
		},
		//玩家准备开始游戏
		readyGame: function(username){
			let i=0;
			for(i=0;i<vue.queue.length;i++){
				if(vue.queue[i].name==username){
					vue.queue[i].ready=4;
				}
			}
		},
		//获胜状态数字转中文
		toPeaceWords: function(peaceNum){
			if(peaceNum==1){
				return "胜";
			}else if(peaceNum==2){
				return "败";
			}else if(peaceNum==3){
				return "和";
			}
		},
		//留言板留言
		addMessage: function(username,message){
			if(username=="颜姬Channel"){
				if((vue.messages.length>=1&&vue.messages[0].name=="颜姬Channel")||vue.messages.length>=3){
					vue.messages.shift();
				}
				vue.messages.unshift({"name":username,"text":message});
			}else{
				vue.messages.push({"name":username,"text":message});
				if(vue.messages.length>3){
					if(vue.messages[0].name=="颜姬Channel"){
						vue.messages[1] = vue.messages[2];
						vue.messages[2] = vue.messages[3];
						vue.messages.pop();
					}else{
						vue.messages.shift();
					}
				}
			}
		},
		//清空留言板留言
		clearMessage: function(){
			vue.messages = [];
		},
		//添加vip
		addVip: function(username){
			if(vue.isVip(username)){
				return;
			}
			vipList.push(username);
		},
		//判断是否vip
		isVip: function(username){
			for(let i=0;i<vipList.length;i++){
				if(vipList[i]==username){
					return true;
				}
			}
			return false;
		},
		//测试屏蔽词
		testWord: function(){
			//仅“停止游戏”状态且无进行中对局时可以测试屏蔽词
			if(vue.status==1||vue.exit==0){
				vue.output("进入测试屏蔽词模式失败");
				return;
			}
			if(inTestWord){
				vue.output("已在测试屏蔽词模式中");
				return;
			}
			vue.output("进入测试屏蔽词模式成功");
			vue.logs=[];
			vue.step_count=0;
			
			timer("屏蔽词测试",5,0);
			inTestWord = setInterval(function(){
				//给数组不重复地添加元素
				function addUnique(arr, str){
					for(let j=0;j<arr.length;j++){
						if(arr[j] == str){
							return;
						}
					}
					arr.push(str);
				}
				function remove(arr, str){
					let j,k;
					for(j=0;j<arr.length;j++){
						if(arr[j] == str){
							break;
						}
					}
					if(j<arr.length){
						for(k=j;k<arr.length-1;k++){
							arr[k]=arr[k+1];
						}
						arr.pop();
					}
				}
				vue.step_count++;
				timer("屏蔽词测试",5,0);
				let testResult;
				let i;
				do{
					testResult = getTestWord(vue.step_count);
					for(i=0;i<passedWordsArr.length;i++){
						if(passedWordsArr[i] == testResult){
							break;
						}
					}
				//如果行棋语句不合规，或者已经测试通过，则换一条行棋语句测试
				}while(!testResult || i<passedWordsArr.length);
				vue.logs.push({
					"step": vue.step_count,
					"content": testResult,
					"test": "test"
				});
				vue.output(testResult);
				if(vue.logs.length > 26){
					if(vue.logs[0].test == "test"){
						addUnique(blockedWordsArr,vue.logs[0].content);
					}else{
						addUnique(passedWordsArr,vue.logs[0].content);
						remove(blockedWordsArr,vue.logs[0].content);
					}
					if(vue.logs[1].test == "test"){
						addUnique(blockedWordsArr,vue.logs[1].content);
					}else{
						addUnique(passedWordsArr,vue.logs[1].content);
						remove(blockedWordsArr,vue.logs[1].content);
					}
					vue.logs.shift();
					vue.logs.shift();
					let blockedWords = "";
					for(let j=0;j<blockedWordsArr.length;j++){
						blockedWords += blockedWordsArr[j];
						if(j<blockedWordsArr.length-1){
							blockedWords += "、";
						}
					}
					vue.addMessage("颜姬Channel","被屏蔽的行棋语句为：" + blockedWords + "。");
				}
			}, 5000);
		},
		//停止测试屏蔽词
		testWordEnd: function(){
			clearInterval(inTestWord);
			inTestWord=null;
		},
		//给用户名添加对应头像
		addImage: function(username, uid){
			//检查用户头像是否已存在，如不存在则存储头像
			let i=0;
			for(i=0;i<vue.images.length;i++){
				if(vue.images[i].username == username){
					break;
				}
			}
			if(i<vue.images.length){
				if(vue.images[i].image != ""){
					return;
				}
			}
			if(i==vue.images.length){
				vue.images.push({"username":username,"image":DEFAULT_AVATAR_URL});	
			}
			axios.get("/face?uid="+uid).then(function(res){
				let imageUrl = res.data + "@100w_100h";
				vue.images[i].image = imageUrl;
			}).catch(function(err){
				console.error(err);
				vue.images[i].image = "";
			});
		},
		//获取用户名对应头像
		getImage: function(username){
			let i=0;
			for(i=0;i<vue.images.length;i++){
				if(vue.images[i].username == username){
					return vue.images[i].image;
				}
			}
			if(i==vue.images.length){
				return DEFAULT_AVATAR_URL;
			}
		},
		//弹幕输出（对接blivemessagesender）
		output: function(message){
			console.log(message);
			try{
				axios.post("/receive",{
					message: message
				}).catch(function(err){
					console.error(err);
				});
			}catch(e){
				console.error(e);
			}
		},
		//管理员控制
		onAdminCommand: function(commands){
			try{
				if(commands[1].toLowerCase()=="addqueue"){//管理员让用户插队 admin addqueue username point end
					vue.addQueue(commands[2],parseInt(commands[3]));
					vue.output("admin-ok");
				}else if(commands[1].toLowerCase()=="removequeue"){//管理员把用户移出队列 admin removequeue username end
					vue.removeQueue(commands[2]);
					vue.output("admin-ok");
				}else if((commands[1].toLowerCase()=="exit"&&vue.exit==0)//管理员[定时](或取消)停止游戏 admin exit [time]|[cancel] end
						||(commands[1].toLowerCase()=="start"&&vue.exit==1)){//管理员[定时](或取消)启动游戏 admin start [time]|[cancel] end
					let m = "";
					if(commands[2].toLowerCase()=="end"){
						if(vue.exit==0){
							vue.exit=1;
							m = "管理员已停止排队";
						}else if(vue.exit==1){
							vue.exit=0;
							vue.startGame();
							m = "管理员已开启游戏";
						}
						vue.switchTime=null;
					}else if(commands[2].toLowerCase()=="cancel"){
						vue.switchTime=null;
						m = "管理员已取消定时";
					}else{
						let now = new Date();
						let switchTime = now;
						let hour = now.getHours();
						let minute = now.getMinutes();
						if(hour>parseInt(commands[2].substring(0,2))||(hour==parseInt(commands[2].substring(0,2))
								&&minute>=parseInt(commands[2].substring(2,4)))){
							switchTime.setDate(now.getDate()+1);
						}
						switchTime.setHours(parseInt(commands[2].substring(0,2)));
						switchTime.setMinutes(parseInt(commands[2].substring(2,4)));
						switchTime.setSeconds(0);
						vue.switchTime = switchTime;
						m = "管理员已设定"+commands[2].substring(0,2)+":"+commands[2].substring(2,4)+(vue.exit?"启动游戏":"停止排队");
					}
					vue.output("admin-ok");
					vue.$notify({
						message:m,
						duration:8000,
						type:"success",
						showClose:false,
						position:"bottom-right"
					});
				}else if(commands[1].toLowerCase()=="endgame"&&vue.status==1){//管理员强行结束棋局 admin endgame end
					vue.endGame();
					vue.output("admin-ok");
				}else if(commands[1].toLowerCase()=="message"){//管理员发送留言 admin message content [...] end
					let content = "";
					for(let i=2; i<commands.length-1; i++){
						content += commands[i];
						if(i<commands.length-2){
							content += " ";
						}
					}
					vue.addMessage("颜姬Channel",content);
					vue.output("admin-ok");
				}else if(commands[1].toLowerCase()=="clear"){//管理员清空留言 admin clear end
					vue.clearMessage();
					vue.output("admin-ok");
				}else if(commands[1].toLowerCase()=="addvip"){//管理员添加vip名单 admin addvip username end
					vue.addVip(commands[2]);
					vue.output("admin-ok");
				}else if(commands[1].toLowerCase()=="test"){//管理员测试屏蔽词 admin test end
					vue.testWord();
				}else if(commands[1].toLowerCase()=="testend"){//管理员结束测试屏蔽词 admin testend end
					vue.testWordEnd();
					vue.output("退出测试屏蔽词模式成功");
				}else if(commands[1].toLowerCase()=="recentdm"){//管理员检查最近弹幕时间 admin recentdm end
					vue.output("最近弹幕发送时间"+vue.dateToHmm(vue.recentdm));
				}else if(commands[1].toLowerCase()=="recentgame"){//管理员检查最近对局时间 admin recentgame end
					vue.output("最近对局结束时间"+vue.dateToHmm(vue.recentgame));
				}else{
					vue.output("admin-error");
					vue.$notify({
						message:"admin error",
						duration:5000,
						type:"error",
						showClose:false,
						position:"bottom-right"
					});
				}
			}catch(err){
				console.error(err);
				vue.output("admin-error");
				vue.$notify({
					message:"admin error",
					duration:5000,
					type:"error",
					showClose:false,
					position:"bottom-right"
				});
			}
		},
		//js Date类型转时间文字HH:mm
		dateToHmm: function(date){
			if(date==null){
				return "无";
			}
			let hour = date.getHours();
			if(hour < 10){
				hour = "0" + hour;
			}
			let minute = date.getMinutes();
			if(minute < 10){
				minute = "0" + minute;
			}
			return hour+":"+minute;
		},
		//接收弹幕(本方法对接bilibili_danmuji)
		onMessage: function(username,message,uid,privilegeType){
			//更新头像
			vue.addImage(username,uid);
			//更新最近弹幕时间（主播和房管的弹幕不计入）
			if(username!="颜姬Channel"&&username!="颜姬Studio"){
				vue.recentdm = new Date();
			}
			//添加vip列表（大航海）
			if(privilegeType>0){
				vue.addVip(username);
			}
			//管理员控制
			if(username=="颜姬Channel"){
				if(adminCommands.length>0||message.toLowerCase()=="admin"
						||(message.length>=6&&message.substring(0,6).toLowerCase()=="admin ")){
					let m = message.split(" ");
					for(let i=0;i<m.length;i++){
						if(m[i]!=""){
							adminCommands.push(m[i]);
						}
					}
					if(adminCommands[adminCommands.length-1].toLowerCase()=="end"){
						vue.onAdminCommand(adminCommands);
						adminCommands=[];
					}
				}
			}
			//屏蔽词测试模式
			if(inTestWord){
				if(message.length==4&&username=="颜姬Studio"){
					for(let i=0; i<vue.logs.length; i++){
						if(vue.logs[i].content == message){
							vue.logs[i].test = "success";
						}
					}
				}
			}
			if(message=="打卡"){
				vue.$notify({
					message:"滴~"+username+"打卡成功",
					duration:8000,
					type:"success",
					showClose:false,
					position:"bottom-right"
				});
				return;
			}
			if((message=="排队"||message=="排隊")	&&username!=vue.red_rival_name&&username!=vue.black_rival_name){
				vue.addQueue(username,0);
				if(vue.exit==1){
					vue.output("游戏已停止，排队失败");
				}else if(vue.exit==0){
					if(vue.status==0){
						if(username.length>10){
							username=username.substring(0,8)+"*"+username.substring(username.length-1);
						}
						vue.output(username+"排队成功，请【准备】");
					}else{
						if(username.length>16){
							username=username.substring(0,14)+"*"+username.substring(username.length-1);
						}
						vue.output(username+"排队成功");
					}
				}
				return;
			}
			if(message=="退出"&&username!=vue.red_rival_name&&username!=vue.black_rival_name){
				vue.removeQueue(username);
				return;
			}
			if(vue.status==0){
				if(message=="准备"||message=="準備"){
					vue.readyGame(username);
				}
			}else if(vue.status==1){
				if(username==vue.red_rival_name){
					if(message=="认输"||message=="認輸"||message=="退出"){
						vue.output("红方认输，黑方胜");
						vue.red_peace=2;
						vue.black_peace=1;
						vue.endGame();
						return;
					}
					if(message=="和棋"){
						vue.red_peace=3;
					}
					if(message=="取消"){
						vue.red_peace=0;
					}
					if(vue.color==0){
						vue.onStep(message,0);
					}
				}else if(username==vue.black_rival_name){
					if(message=="认输"||message=="認輸"||message=="退出"){
						vue.output("黑方认输，红方胜");
						vue.red_peace=1;
						vue.black_peace=2;
						vue.endGame();
						return;
					}
					if(message=="和棋"){
						vue.black_peace=3;
					}
					if(message=="取消"){
						vue.black_peace=0;
					}
					if(vue.color==1){
						vue.onStep(message,1);
					}
				}
				if(vue.red_peace==3&&vue.black_peace==3){
					vue.output("双方和棋，游戏结束");
					vue.endGame();
				}
			}
		},
		//接收礼物(本方法对接blivechat)
		onGift: function(username,giftName,price){
			//添加vip
			if(price>=1){
				vue.addVip(username);
			}
			vue.output("感谢"+username+"赠送的"+giftName);
			//如送礼用户已在排队队列中，则给队列中用户加点
			let i=0;
			for(i=0;i<vue.queue.length;i++){
				if(vue.queue[i].name==username){
					vue.addQueue(username,price*10);
					return;
				}
			}
			//否则添加到隐藏的送礼用户中
			for(i=0;i<vue.donators.length;i++){
				if(vue.donators[i].username==username){
					vue.donators[i].point+=price*10;
					break;
				}
			}
			if(i==vue.donators.length){
				vue.donators.push({"username":username,point:price*10});
			}
		},
		//接收SuperChat(本方法对接blivechat)
		onSuperChat: function(username,message){
			vue.addMessage(username,message);
			vue.output("感谢"+username+"的超级留言");
		}
	}
});
//websocket连接弹幕后台服务
function connectWs(){
	console.log("弹幕服务器正在连接"+websocketURL);
	try{
		socket = new WebSocket(websocketURL);
		socket.onopen = function(){
			vue.$notify({
				message:"弹幕服务器连接成功",
				duration:5000,
				type:"info",
				showClose:false,
				position:"bottom-right"
			});
		};
		socket.onmessage = function(msg){
			let data = JSON.parse(msg.data);
			if(data.cmd == "danmu"){//弹幕
				let username = data.result.uname;
				let message = data.result.msg;
				let uid = data.result.uid;
				let privilegeType = data.result.uguard;
				vue.onMessage(username,message,uid,privilegeType);
			}else if(data.cmd == "gift"){//免费和付费礼物，以及大航海
				let username = data.result.uname;
				let giftName = data.result.giftName;
				let num = data.result.num;
				let price = 0;
				if(data.result.coin_type===1){
					price = data.result.total_coin / 1000;
				}
				vue.onGift(username,giftName,price);
				let duration = 5000;
				if(price >= 100){
					duration = 3600000;
				}else if(price >= 10){
					duration = 360000;
				}else if(price >= 1){
					duration = 60000;
				}else if(price > 0){
					duration = 10000;
				}
				vue.$notify({
					message:"感谢"+username+"赠送的"+giftName+"×"+num,
					duration:duration,
					type:"info",
					showClose:false,
					position:"bottom-right"
				});
			}else if(data.cmd == "superchat"){//superchat
				let username = data.result.uname;
				let message = data.result.message;
				vue.onSuperChat(username,message);
			}
		};
		socket.onclose = function(){
			vue.$notify({
				message:"弹幕服务器已关闭",
				duration:5000,
				type:"info",
				showClose:false,
				position:"bottom-right"
			});
		};
		socket.onerror = function(err){
			console.error(err);
			vue.$notify({
				message:"弹幕服务器连接失败",
				duration:8000,
				type:"error",
				showClose:false,
				position:"bottom-right"
			});
		};
	}catch(err){
		console.error(err);
		vue.$notify({
			message:"弹幕服务器连接失败",
			duration:8000,
			type:"error",
			showClose:false,
			position:"bottom-right"
		});
	}
}
connectWs();
</script>
</body>
